<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>03-画一个三角形(缓冲区对象)</title>

</head>
<body>
    <canvas id="canvas" width = "400" height = "400"></canvas>
</body>
<script src="../lib/webgl-utils2.js"></script>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
        attribute vec4 my_Position;
        void main() {
            gl_Position = my_Position;
            gl_PointSize = 15.0;
        }
    </script>

<script id="2d-fragment-shader" type="x-shader/x-fragment">
        void main() {
            gl_FragColor = vec4(0.0,1.0,1.0,1.0);
        }
    </script>
</html>
<script>
    // 参考： https://blog.csdn.net/charlee44/article/details/100534038
    // 1.如果需要绘制如三角形、矩形或者立方体等稍微复杂的图形，这个时候就需要一种很方便的机制——缓冲区对象（buffer object）。
    // 2.OpenGL/WebGL进行图形工作，需要访问显存的数据。而像C或者JS这样的编程语言去申请数据，总是保存在内存中——也就是说，
    //      需要把内存中的数据传输到显存，OpenGL/WebGL才能进行绘制。数据的申请、传输、释放是一种IO操作，对IO操作而言，分段的、多次的
    //      读写操作的效率总是比不上一次总体的读写操作。缓冲区对象正是用来解决这两个问题的,
    //      我们可以一次性向缓冲区对象填充大量的顶点数据，供顶点着色器使用。
    // 3.一般来说，任何三维模型的基本单位就是三角形，会绘制三角形就能绘制任意复杂的图形。

    // Get A WebGL context 获取一个上下文
    var canvas = document.getElementById("canvas");
    var gl = canvas.getContext("experimental-webgl");

    // setup a GLSL program 设置一个着色器描述语言 即设置顶点着色器，片元着色器
    var program = createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]);
    gl.useProgram(program);

    //清理背景色
    gl.clearColor(0.0,0.0,0.0,1.0);

    //清理画布
    gl.clear(gl.COLOR_BUFFER_BIT);

    //给定一个顶点数组 即三角形的三个顶点位置
    // Float32Array是WebGL引入的特殊的类型化数组，能够保存大量同一种类型的元素
    var vertexPointArray = new Float32Array([
        0, 0.5,   -0.5, -0.5,   0.5, -0.5
    ]);
    //上边的数组数据通过缓冲区对象传入顶点着色器，需要如下五个步骤：
    //1.创建缓冲区对象：WebGL通过gl.createBuffer()来创建缓冲区对象，它告诉WebGL系统，开辟显存空间接受内存传输过来的数据
    var buffer = gl.createBuffer();
    //2.绑定缓冲区对象(gl.bindBuffer())
    // 由于缓冲区对象可能有多种用途，创建缓冲区之后还需要将其绑定到不同目标上，
    // 参数 gl.ARRAY_BUFFER 表示缓冲区对象存储的是关于顶点的数据。
    // 参数 gl.ELEMENT_ARRAY_BUFFER 表示缓冲区对象存储的是关于顶点的索引值。
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
    //3.将数据写入缓冲区对象(gl.bufferData())
    // 将数组vertexPointArray中的数据 传输到目标gl.ARRAY_BUFFER上的缓冲区对象
    //其中 gl.STATIC_DRAW 代表 只会向缓冲区对象中写入一次数据 但需要绘制很多次
    //其中 gl.STREAM_DRAW 代表 只会向缓冲区对象中写入一次数据 然后绘制若干次
    //其中 gl.STATIC_DRAW 代表 会向缓冲区对象中多次写入数据 并绘制多次
    gl.bufferData(gl.ARRAY_BUFFER,vertexPointArray,gl.STATIC_DRAW);
    //4.将缓冲区对象分配给attribute变量(gl.vertexAttribPointer())
    //获取顶点着色器的变量
    var my_Position = gl.getAttribLocation(program, "my_Position");
    //这里用过函数gl.vertexAttribPointer()，将整个缓冲区对象，也就是顶点数据，一次性分配给顶点着色器attribute变量my_Position
    // 第一个参数 将绑定到 gl.ARRAY_BUFFER的缓冲区对象分配给 由 location指定的attribute变量
    // 第二个参数GLint size是指的维度, 指定缓冲区中每个顶点的分量个数（1到4）。若size的值比 attribute变量需要的分量个数少，则执行补全规则。
    // 第三个参数GLenum type是指参数类型，包括gl.INT,gl.FLOAT,gl.SHORT等等多种。
    // 第四个参数GLboolean normalized 是指是否将非浮点型的数据规划到[0,1]或者[-1,1]区间，
    // 第五个参数GLsizei stride， 相邻两个顶点间字节数，默认为0
    // 第六个参数GLintptr offset，绑定的缓冲区偏移offset个字节开始读数据，默认为0，这里offset=0,指从绑定缓冲区首地址开始读。
    gl.vertexAttribPointer(my_Position, 2, gl.FLOAT, false, 0, 0);
    //5.开启attribute变量(gl.enableVertexAttribArray()) : 开启attribute变量，建立缓冲区与attribute变量的连接 （类似于数据共享？？）
    gl.enableVertexAttribArray(my_Position);

    //绘制三角形
    gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>

